home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 February: Tool Chest / Dev.CD Feb 00 TC.toast / pc / tool chest / development kits / hypercard related / xcmds & xfcns / byrne's xcmds&xfcns / source / createcopy.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-06  |  10.7 KB  |  380 lines

  1. /*
  2.  
  3.     CreateCopy XCMD v1.2
  4.     
  5.     ©1990-1 Apple Computer, Inc.; by Mike Byrne
  6.     
  7.     CreateCopy will create a copy of any file specified by the origin pathname (must be a full 
  8.     pathname) to the file specified by the destination.  There must not be a file in the target
  9.     directory with the same name as that specified in the destination path.  Adhering to XCMD
  10.     guidelines, this is not to take up more than 32K of memory, so this is *really* slow with
  11.     large files (it does them 32K at a time).
  12.     
  13.     Form:
  14.     CreateCopy <origin file pathname> <destination file pathname>
  15.     
  16.     # the MPW 3.2 build commands:
  17.     C -b CreateCopy.c -mbg off
  18.         Link -w -t STAK -c WILD -rt XCMD=604 ∂
  19.             -m ENTRYPOINT ∂
  20.             -sg CreateCopy ∂
  21.             CreateCopy.c.o ∂
  22.             "{Libraries}HyperXLib.o" ∂
  23.             "{Libraries}Runtime.o" ∂
  24.             "{Libraries}Interface.o" ∂
  25.             "{CLibraries}StdCLib.o" ∂
  26.             -o "teststack"
  27. */
  28.  
  29. #include <Types.h>
  30. #include <Files.h>
  31. #include <string.h>
  32. #include <Memory.h>
  33. #include <Packages.h>
  34. #include "HyperXCmd.h"
  35.  
  36. #define NULL 0L
  37. #define NIL 0L
  38.  
  39. #define kNumParams 2
  40. #define k32kbytes 32768        //size of 32K
  41.  
  42.  
  43. /* prototypes */
  44. void ErrorBack(XCmdPtr paramPtr, char *message);
  45. void MoveLockParams ( XCmdPtr paramPtr, short paramCount );
  46. void UnlockParams  ( XCmdPtr paramPtr, short paramCount );
  47.  
  48.  
  49.  
  50. pascal void EntryPoint(XCmdPtr paramPtr)
  51. {
  52.     short        i,j;
  53.     Handle        theBuffer;
  54.     char        orgName[301];
  55.     char        orgVol[34];
  56.     char        destName[301];
  57.     char        destVol[34];
  58.     short        orgVRefNum = 0;
  59.     short        destVRefNum = 0;
  60.     short        orgRef;
  61.     short        destRef;
  62.     FInfo        fndrInfo;
  63.     OSType        type = 0;
  64.     OSType        creator = 0;
  65.     long        fileLength;
  66.     long        fullBlocks;
  67.     long        partialBlock;
  68.     long        blockSize = k32kbytes;    
  69.  
  70.  
  71.     
  72.     /* move high and lock the parameters. */
  73.     MoveLockParams(paramPtr, paramPtr->paramCount);
  74.  
  75.     /* check for syntax or copyright help request */
  76.     if (!strcmp( (char*)*paramPtr->params[0], "!") ) {
  77.         ErrorBack(paramPtr, "v1.2, by Mike Byrne, ©1990-1 Apple Computer, Inc.");
  78.         UnlockParams(paramPtr, paramPtr->paramCount);
  79.         return;
  80.     } else if (!strcmp ( (char*)*paramPtr->params[0], "?") ) {
  81.         ErrorBack(paramPtr, "CreateCopy syntax is 'CreateCopy <origin filepath> <destination filepath>'");
  82.         UnlockParams(paramPtr, paramPtr->paramCount);
  83.         return;
  84.     }
  85.  
  86.     /* check for correct number of parameters *.
  87.     if (paramPtr->paramCount != kNumParams) {
  88.         ErrorBack(paramPtr, "Error: CreateCopy syntax is 'CreateCopy <origin filepath> <destination filepath>'");
  89.         return;
  90.     }
  91.  
  92.  
  93.     /*  THE ORIGIN FILE
  94.         extract the volume name from the handle, copy to a pas string,
  95.          and get the volume reference number of the volume              */
  96.     for (i=0; ((*(paramPtr->params[0]))[i] != ':' && (i < 33)); i++) 
  97.         { orgVol[i] = (*(paramPtr->params[0]))[i]; }
  98.     orgVol[i] = ':';
  99.     orgVol[i+1] = '\0'; 
  100.     c2pstr(orgVol);
  101.  
  102.     if (SetVol(orgVol, orgVRefNum) != noErr) {                            // toolbox
  103.         ErrorBack(paramPtr, "Error: Could not set the default origin volume");
  104.         UnlockParams(paramPtr, kNumParams);
  105.         return;
  106.     }
  107.     
  108.     if (GetVol(&orgVol, &orgVRefNum) != noErr) {                        // toolbox
  109.         ErrorBack(paramPtr, "Error: Could not find the origin volume requested.");
  110.         UnlockParams(paramPtr, kNumParams);
  111.         return;
  112.     }
  113.  
  114.     /* now, copy the rest of the pathname to the partial pathname and convert it. */
  115.     for (j=i; (j <= strlen((*(paramPtr->params[0]))) && (j < 300)); j++) 
  116.         { orgName[j-i] = (*(paramPtr->params[0]))[j]; }
  117.     c2pstr(orgName);
  118.  
  119.     /* open the origin file  */
  120.     if ( FSOpen(orgName, orgVRefNum, &orgRef) != noErr) {                // toolbox
  121.         ErrorBack(paramPtr, "Error: Cannot open source file.");
  122.         UnlockParams(paramPtr, kNumParams);
  123.         return; 
  124.     }
  125.         
  126.     /* get the type and creator of the origin file */
  127.     if (GetFInfo(orgName, orgVRefNum, &fndrInfo) != noErr) {            // toolbox
  128.         ErrorBack(paramPtr, "Error: Could not access file type and creator.");
  129.         UnlockParams(paramPtr, kNumParams);
  130.         FSClose(orgRef);
  131.         return;
  132.     }
  133.     type = fndrInfo.fdType;
  134.     creator = fndrInfo.fdCreator;
  135.     
  136.     /* find out how big the origin file is */
  137.     if ( GetEOF(orgRef, &fileLength) != noErr) {                        // toolbox
  138.         ErrorBack(paramPtr, "Error: Cannot find end-of-file for the origin file.");
  139.         UnlockParams(paramPtr, kNumParams);
  140.         FSClose(orgRef);
  141.         return;
  142.     }
  143.     
  144.     
  145.     /* reset loop counters */
  146.     i = j = 0;
  147.     /*  THE DESTINATION FILE
  148.         extract the volume name from the handle, copy to a pas string,
  149.          and get the volume reference number of the volume              */
  150.     for (i=0; ((*(paramPtr->params[1]))[i] != ':' && (i < 33)); i++) 
  151.         { destVol[i] = (*(paramPtr->params[1]))[i]; }
  152.     destVol[i] = ':';
  153.     destVol[i+1] = '\0'; 
  154.     c2pstr(destVol);
  155.     
  156.     if (SetVol(destVol, destVRefNum) != noErr) {                        // toolbox
  157.         ErrorBack(paramPtr, "Error: Could not set the default destination volume");
  158.         UnlockParams(paramPtr, kNumParams);
  159.         FSClose(orgRef);
  160.         return;
  161.     }
  162.     
  163.     if (GetVol(&destName, &destVRefNum) != noErr) {                        // toolbox
  164.         ErrorBack(paramPtr, "Error: Could not find the destination volume requested.");
  165.         UnlockParams(paramPtr, kNumParams);
  166.         FSClose(orgRef);
  167.         return;
  168.     }
  169.  
  170.     /* now, copy the rest of the pathname to the partial pathname and convert it. */
  171.     for (j=i; (j <= strlen((*(paramPtr->params[1]))) && (j < 300)); j++) 
  172.         { destName[j-i] = (*(paramPtr->params[1]))[j]; }
  173.     c2pstr(destName);
  174.  
  175.     /* now, create the destination file. */
  176.     if (Create(destName, destVRefNum, creator, type) != noErr) {        // toolbox
  177.         ErrorBack(paramPtr, "Error: Could not create destination file");
  178.         UnlockParams(paramPtr, kNumParams);
  179.         FSClose(orgRef);
  180.         return;
  181.     }
  182.     
  183.     /*  open the destination file */
  184.     if (FSOpen(destName, destVRefNum, &destRef) != noErr) {                // toolbox
  185.         ErrorBack(paramPtr, "Error: Could not open destination file.");
  186.         UnlockParams(paramPtr, kNumParams);
  187.         FSClose(orgRef);
  188.         return;
  189.     }
  190.     
  191.     /*     THE ACTUAL COPYING PART        */
  192.     /* check out how many blocks will be necessary. */    
  193.     fullBlocks = fileLength / blockSize;
  194.     partialBlock = fileLength % blockSize;
  195.     
  196.  
  197.     if ((theBuffer = NewHandleClear((Size)blockSize)) == 0) {
  198.         ErrorBack(paramPtr, "Error: Cannot allocate the 32K for the copy.");
  199.         UnlockParams(paramPtr, kNumParams);
  200.         FSClose(orgRef);
  201.         FSClose(destRef);
  202.         return;
  203.     }
  204.  
  205.     MoveHHi(theBuffer);
  206.     
  207.     /* iterate through the number of 32K blocks */
  208.     for (i=1; i <= fullBlocks; i++) {
  209.         /* read for 32K (or whatever)  */
  210.         if (FSRead(orgRef, &blockSize, *theBuffer) != noErr) {            // toolbox
  211.             ErrorBack(paramPtr, "Error: Could not read from origin file");
  212.             DisposHandle(theBuffer);
  213.             UnlockParams(paramPtr, kNumParams);
  214.             FSClose(orgRef);
  215.             FSClose(destRef);
  216.             return;
  217.         }
  218.         /* write however many were read in */
  219.         if (FSWrite(destRef, &blockSize, *theBuffer) != noErr) {         // toolbox
  220.             ErrorBack(paramPtr, "Error: Could not write to destination file.");
  221.             DisposHandle(theBuffer);
  222.             UnlockParams(paramPtr, kNumParams);
  223.             FSClose(orgRef);
  224.             FSClose(destRef);
  225.             return;
  226.         }
  227.     }
  228.     
  229.     /* now, do the partial block */
  230.     if (FSRead(orgRef, &partialBlock, *theBuffer) != noErr) {            // toolbox
  231.         ErrorBack(paramPtr, "Error: Could not read from origin file");
  232.         DisposHandle(theBuffer);
  233.         UnlockParams(paramPtr, kNumParams);
  234.         FSClose(orgRef);
  235.         FSClose(destRef);
  236.         return;
  237.     }
  238.     /* write however many were read in */
  239.     if (FSWrite(destRef, &partialBlock, *theBuffer) != noErr) {         // toolbox
  240.         ErrorBack(paramPtr, "Error: Could not write to destination file.");
  241.         DisposHandle(theBuffer);
  242.         UnlockParams(paramPtr, kNumParams);
  243.         FSClose(orgRef);
  244.         FSClose(destRef);
  245.         return;
  246.     }
  247.     
  248.     /* okay, the copying of the data fork is finished.  close the data forks. */
  249.     FSClose(orgRef);
  250.     FSClose(destRef);
  251.     
  252.     /* all that crap we did?  do it again for the resource fork... */
  253.     /* open the origin file  */
  254.     if ( OpenRF(orgName, orgVRefNum, &orgRef) != noErr) {                // toolbox
  255.         ErrorBack(paramPtr, "Error: Cannot open source file resource fork.");
  256.         DisposHandle(theBuffer);
  257.         UnlockParams(paramPtr, kNumParams);
  258.         return; 
  259.     }
  260.         
  261.     /* find out how big the origin file is */
  262.     if ( GetEOF(orgRef, &fileLength) != noErr) {                        // toolbox
  263.         ErrorBack(paramPtr, "Error: Cannot find end-of-file for the origin file resource fork.");
  264.         DisposHandle(theBuffer);
  265.         UnlockParams(paramPtr, kNumParams);
  266.         FSClose(orgRef);
  267.         return;
  268.     }
  269.     
  270.     /*  open the destination file */
  271.     if (OpenRF(destName, destVRefNum, &destRef) != noErr) {                // toolbox
  272.         ErrorBack(paramPtr, "Error: Could not open destination file resource fork.");
  273.         DisposHandle(theBuffer);
  274.         UnlockParams(paramPtr, kNumParams);
  275.         FSClose(orgRef);
  276.         return;
  277.     }
  278.  
  279.     /* set up block sizes */
  280.     fullBlocks = fileLength / blockSize;
  281.     partialBlock = fileLength % blockSize;
  282.     
  283.     /* iterate through the number of 32K blocks */
  284.     for (i=1; i <= fullBlocks; i++) {
  285.         /* read for 32K (or whatever)  */
  286.         if (FSRead(orgRef, &blockSize, *theBuffer) != noErr) {            // toolbox
  287.             ErrorBack(paramPtr, "Error: Could not read from origin file");
  288.             DisposHandle(theBuffer);
  289.             UnlockParams(paramPtr, kNumParams);
  290.             FSClose(orgRef);
  291.             FSClose(destRef);
  292.             return;
  293.         }
  294.         /* write however many were read in */
  295.         if (FSWrite(destRef, &blockSize, *theBuffer) != noErr) {         // toolbox
  296.             ErrorBack(paramPtr, "Error: Could not write to destination file.");
  297.             DisposHandle(theBuffer);
  298.             UnlockParams(paramPtr, kNumParams);
  299.             FSClose(orgRef);
  300.             FSClose(destRef);
  301.             return;
  302.         }
  303.     }
  304.     
  305.     /* now, do the partial block */
  306.     if (FSRead(orgRef, &partialBlock, *theBuffer) != noErr) {            // toolbox
  307.         ErrorBack(paramPtr, "Error: Could not read from origin file");
  308.         DisposHandle(theBuffer);
  309.         UnlockParams(paramPtr, kNumParams);
  310.         FSClose(orgRef);
  311.         FSClose(destRef);
  312.         return;
  313.     }
  314.     /* write however many were read in */
  315.     if (FSWrite(destRef, &partialBlock, *theBuffer) != noErr) {         // toolbox
  316.         ErrorBack(paramPtr, "Error: Could not write to destination file.");
  317.         DisposHandle(theBuffer);
  318.         UnlockParams(paramPtr, kNumParams);
  319.         FSClose(orgRef);
  320.         FSClose(destRef);
  321.         return;
  322.     }
  323.     
  324.     /* okay, the copying of the resource fork is finished.  close 'em, clean up, go home. */
  325.     FSClose(orgRef);
  326.     FSClose(destRef);
  327.     DisposHandle(theBuffer);
  328.     UnlockParams(paramPtr, kNumParams);
  329.     return;
  330. }
  331.  
  332.  
  333.  
  334.  
  335.  
  336.     
  337. /* allocate and load up paramPtr->returnValue with a string 
  338.    -------------------------------------------------------- */
  339. void ErrorBack(XCmdPtr paramPtr, char *message)
  340. {
  341.     Handle  mesHnd;
  342.  
  343.     /*
  344.         Allocate space for an error message.
  345.         Copy the string into it.
  346.         Return the handle to HyperCard.
  347.     */
  348.     mesHnd = NewHandle((long)(strlen(message)+1));
  349.     if (mesHnd == nil) return;
  350.     strcpy((char *)*mesHnd,message);
  351.     paramPtr->returnValue = mesHnd;
  352. }
  353.  
  354.  
  355.  
  356. /*  move high and lock down all parameters (watch that these are read-only) 
  357.     ----------------------------------------------------------------------- */
  358. void MoveLockParams ( XCmdPtr paramPtr, short paramCount )
  359. {
  360.     short i;
  361.     
  362.     for(i=0; i <= paramCount-1; i++)
  363.     {
  364.         MoveHHi(paramPtr->params[i]);
  365.         HLock(paramPtr->params[i]);
  366.     }
  367. }
  368.  
  369.  
  370.  
  371.  
  372. /* unlock all parameter handles in the XCmdBlock  
  373.    ---------------------------------------------  */
  374. void UnlockParams  ( XCmdPtr paramPtr, short paramCount )
  375. {    short i;
  376.     
  377.     for(i=0; i <= paramCount-1; i++)
  378.         { HUnlock(paramPtr->params[i]);}
  379. }
  380.